import { normalizeWhitespace } from './interactive-elements.js';

const MAX_HTML_PREVIEW_LENGTH = 4000;
const MAX_TEXT_LENGTH = 6000;
const HTML_HEURISTIC_RE = /<([a-z][\w-]*)(\s[^>]*)?>/i;

const JD_CARD_SELECTOR = '.plugin_goodsCardWrapper';

const createDocumentFromHtml = (html) => {
  if (typeof DOMParser === 'function') {
    try {
      return new DOMParser().parseFromString(html, 'text/html');
    } catch (_) {
      return null;
    }
  }
  if (typeof document !== 'undefined') {
    try {
      const template = document.createElement('template');
      template.innerHTML = html;
      return template.content?.ownerDocument || template.ownerDocument || document;
    } catch (_) {
      return null;
    }
  }
  return null;
};

const parseJDProductsFromHtml = (html) => {
  console.log("[MCP][TOOLS][parseJDProductsFromHtml]", html);
  if (typeof html !== 'string' || !html.includes('plugin_goodsCardWrapper')) {
    return [];
  }

  const doc = createDocumentFromHtml(html);
  if (!doc || typeof doc.querySelectorAll !== 'function') {
    return [];
  }

  const cards = doc.querySelectorAll(JD_CARD_SELECTOR);
  if (!cards || !cards.length) {
    return [];
  }

  const results = [];
  cards.forEach((card, index) => {
    try {
      const titleElement = card.querySelector("[class*='_text']");
      const title = titleElement ? titleElement.textContent.trim() : '';

      const priceElement = card.querySelector("[class*='_price']");
      let price = '';
      if (priceElement) {
        const yenSymbol = priceElement.querySelector("[class*='_yen']")?.textContent?.trim() || '';
        const textNodeType = typeof Node === "undefined" ? 3 : Node.TEXT_NODE;
        const mainPrice = Array.from(priceElement.childNodes || [])
          .filter((node) => node.nodeType === textNodeType)
          .map((node) => (node.textContent || '').trim())
          .join('');
        const decimal = priceElement.querySelector("[class*='_decimal']")?.textContent?.trim() || '';
        price = `${yenSymbol}${mainPrice}${decimal}`.trim();
      }

      const sku = card.getAttribute('data-sku') || '';

      let imgUrl = '';
      const imgElement = card.querySelector("[class*='_img']");
      if (imgElement) {
        imgUrl = imgElement.getAttribute('src') || imgElement.getAttribute('data-src') || '';
        if (imgUrl.startsWith('//')) {
          imgUrl = `https:${imgUrl}`;
        }
      }

      const shopElement = card.querySelector("[class*='_name'] span");
      const shopName = shopElement ? shopElement.textContent.trim() : '';

      const tags = [];
      card.querySelectorAll("[class*='_textTag'] span, [class*='_imgTag'] img").forEach((tag) => {
        const text = (tag.textContent || tag.getAttribute('alt') || '').trim();
        if (text) {
          tags.push(text);
        }
      });

      const volumeElement = card.querySelector("[class*='_goods_volume']");
      const salesInfo = volumeElement ? volumeElement.textContent.trim() : '';

      const titleContainer = card.querySelector("[class*='_goods_title_container']");
      let byTitleContainer = null;
      if (titleContainer) {
        const titleClass = Array.from(titleContainer.classList || []).find((cls) => cls.includes('_goods_title_container'));
        if (titleClass) {
          byTitleContainer = `.${titleClass}`;
        }
      }
      const bySku = sku ? `[data-sku='${sku}']` : null;
      const pointId = card.getAttribute('data-point-id') || null;
      const byPointId = pointId ? `[data-point-id='${pointId}']` : null;

      const selectors = {
        byTitleContainer,
        bySku,
        byPointId,
        generic: "[class*='_goods_title_container']"
      };

      const preferredSelector = byTitleContainer || bySku || byPointId || selectors.generic;

      results.push({
        index: index + 1,
        title,
        price,
        sku,
        selector: preferredSelector || '',
        selectors,
        imgUrl,
        shopName,
        tags,
        salesInfo
      });
    } catch (error) {
      console.warn('[ChromeWebContent] 解析 JD 商品失败:', error);
    }
  });

  const filter = results.filter(Boolean);
  console.log("[MCP][TOOLS][parseJDProductsFromHtml]filter", filter);

  return filter;
};

const looksLikeHtml = (value) => typeof value === 'string' && HTML_HEURISTIC_RE.test(value);

const decodeEntities = (value) => value
  .replace(/&nbsp;/gi, ' ')
  .replace(/&amp;/gi, '&')
  .replace(/&lt;/gi, '<')
  .replace(/&gt;/gi, '>')
  .replace(/&quot;/gi, '"')
  .replace(/&#39;/gi, "'");

const stripScriptsAndStyles = (html) => html
  .replace(/<script[\s\S]*?<\/script>/gi, ' ')
  .replace(/<style[\s\S]*?<\/style>/gi, ' ');

const structuredCloneOrCopy = (value) => {
  if (typeof structuredClone === 'function') {
    try {
      return structuredClone(value);
    } catch (_) {
      // ignore and fall back
    }
  }
  try {
    return JSON.parse(JSON.stringify(value));
  } catch (_) {
    return value;
  }
};

const htmlToInnerText = (html) => {
  if (!looksLikeHtml(html)) {
    return html;
  }

  if (typeof DOMParser === 'function') {
    try {
      const parser = new DOMParser();
      const doc = parser.parseFromString(html, 'text/html');
      if (doc?.body) {
        return doc.body.innerText || doc.documentElement?.innerText || '';
      }
    } catch (error) {
      console.warn('[ChromeWebContent] DOMParser 解析失败:', error);
    }
  }

  const textFallback = stripScriptsAndStyles(html)
    .replace(/<[^>]+>/g, ' ');
  return decodeEntities(textFallback);
};

export const summarizeHtmlPayload = (html) => {
  const innerTextRaw = htmlToInnerText(html);
  const normalizedText = normalizeWhitespace(innerTextRaw);
  const truncatedText = normalizedText.slice(0, MAX_TEXT_LENGTH);
  const textTruncated = normalizedText.length > MAX_TEXT_LENGTH;

  const htmlPreview = html.slice(0, MAX_HTML_PREVIEW_LENGTH);
  const htmlTruncated = html.length > MAX_HTML_PREVIEW_LENGTH;

  return {
    innerText: truncatedText,
    textTruncated,
    htmlPreview,
    htmlTruncated,
    htmlLength: html.length,
    textLength: normalizedText.length
  };
};

export const sanitizeChromeWebContentResult = (payload) => {
  if (payload === null || payload === undefined) {
    return payload;
  }

  if (typeof payload === 'string') {
    const summary = summarizeHtmlPayload(payload);
    const jdProducts = parseJDProductsFromHtml(payload);
    const result = {
      text: summary.innerText,
      textTruncated: summary.textTruncated,
      htmlPreview: summary.htmlPreview,
      htmlTruncated: summary.htmlTruncated,
      htmlLength: summary.htmlLength,
      textLength: summary.textLength,
      htmlOriginal: payload
    };
    if (jdProducts.length) {
      result.productItems = jdProducts;
    }
    return result;
  }

  if (Array.isArray(payload)) {
    return payload.map((item) => sanitizeChromeWebContentResult(item));
  }

  if (typeof payload !== 'object') {
    return payload;
  }

  const clone = structuredCloneOrCopy(payload);

  const visit = (obj) => {
    if (!obj || typeof obj !== 'object') {
      return obj;
    }

    for (const key of Object.keys(obj)) {
      const value = obj[key];

      if (typeof value === 'string') {
        if (looksLikeHtml(value)) {
          const summary = summarizeHtmlPayload(value);
          obj[key] = summary.innerText;
          obj[`${key}HtmlPreview`] = summary.htmlPreview;
          obj[`${key}HtmlTruncated`] = summary.htmlTruncated;
          obj[`${key}TextTruncated`] = summary.textTruncated;
          obj[`${key}HtmlLength`] = summary.htmlLength;
          obj[`${key}TextLength`] = summary.textLength;
          obj[`${key}HtmlOriginal`] = value;
        } else if (value.length > MAX_TEXT_LENGTH) {
          obj[key] = value.slice(0, MAX_TEXT_LENGTH);
          obj[`${key}TextTruncated`] = true;
          obj[`${key}TextLength`] = value.length;
        }
      } else if (Array.isArray(value)) {
        obj[key] = value.map((entry) => sanitizeChromeWebContentResult(entry));
      } else if (value && typeof value === 'object') {
        obj[key] = visit(value);
      }
    }

    const potentialHtmlSources = Object.keys(obj)
      .filter((key) => key.endsWith('HtmlOriginal') && typeof obj[key] === 'string')
      .map((key) => obj[key]);
    const urlIndicatesJD = typeof obj.url === 'string' && obj.url.includes('jd.com');
    const htmlSuggestsJD = potentialHtmlSources.some((html) => typeof html === 'string' && html.includes('plugin_goodsCardWrapper'));
    if (!obj.productItems && potentialHtmlSources.length && (urlIndicatesJD || htmlSuggestsJD)) {
      for (const html of potentialHtmlSources) {
        const parsed = parseJDProductsFromHtml(html);
        if (parsed.length) {
          obj.productItems = parsed;
          break;
        }
      }
    }

    return obj;
  };

  return visit(clone);
};

export const createWebContentPreview = (payload) => {
  if (payload === null || payload === undefined) {
    return '无内容';
  }
  if (typeof payload === 'string') {
    return payload.slice(0, 500);
  }
  try {
    return JSON.stringify(payload).slice(0, 500);
  } catch (error) {
    return String(payload);
  }
};

